home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / io / InputStreamReader.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  7.2 KB  |  274 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)InputStreamReader.java    1.20 98/08/06
  3.  *
  4.  * Copyright 1996-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.io;
  16.  
  17. import sun.io.ByteToCharConverter;
  18. import sun.io.ConversionBufferFullException;
  19.  
  20.  
  21. /**
  22.  * An InputStreamReader is a bridge from byte streams to character streams: It
  23.  * reads bytes and translates them into characters according to a specified
  24.  * character encoding.  The encoding that it uses may be specified by name, or
  25.  * the platform's default encoding may be accepted.
  26.  *
  27.  * <p> Each invocation of one of an InputStreamReader's read() methods may
  28.  * cause one or more bytes to be read from the underlying byte-input stream.
  29.  * For top efficiency, consider wrapping an InputStreamReader within a
  30.  * BufferedReader; for example,
  31.  *
  32.  * <pre>
  33.  * BufferedReader in
  34.  *   = new BufferedReader(new InputStreamReader(System.in));
  35.  * </pre>
  36.  *
  37.  * @see BufferedReader
  38.  * @see InputStream
  39.  *
  40.  * @version     1.20, 98/08/06
  41.  * @author    Mark Reinhold
  42.  * @since    JDK1.1
  43.  */
  44.  
  45. public class InputStreamReader extends Reader {
  46.  
  47.     private ByteToCharConverter btc;
  48.     private InputStream in;
  49.  
  50.     private static final int defaultByteBufferSize = 8192;
  51.     private byte bb[];        /* Input buffer */
  52.  
  53.     /**
  54.      * Create an InputStreamReader that uses the default character encoding.
  55.      *
  56.      * @param  in   An InputStream
  57.      */
  58.     public InputStreamReader(InputStream in) {
  59.     this(in, ByteToCharConverter.getDefault());
  60.     }
  61.  
  62.     /**
  63.      * Create an InputStreamReader that uses the named character encoding.
  64.      *
  65.      * @param  in   An InputStream
  66.      * @param  enc  Name of encoding to be used
  67.      *
  68.      * @exception  UnsupportedEncodingException
  69.      *             If the named encoding is not supported
  70.      */
  71.     public InputStreamReader(InputStream in, String enc)
  72.     throws UnsupportedEncodingException
  73.     {
  74.     this(in, ByteToCharConverter.getConverter(enc));
  75.     }
  76.  
  77.     /**
  78.      * Create an InputStreamReader that uses the specified byte-to-character
  79.      * converter.  The converter is assumed to have been reset.
  80.      *
  81.      * @param  in   An InputStream
  82.      * @param  btc  A ByteToCharConverter
  83.      */
  84.     private InputStreamReader(InputStream in, ByteToCharConverter btc) {
  85.     super(in);
  86.     if (in == null) 
  87.         throw new NullPointerException("input stream is null");
  88.     this.in = in;
  89.     this.btc = btc;
  90.     bb = new byte[defaultByteBufferSize];
  91.     }
  92.  
  93.     /**
  94.      * Returns the canonical name of the character encoding being used by 
  95.      * this stream.  If this <code>InputStreamReader</code> was created 
  96.      * with the {@link #InputStreamReader(InputStream, String)} constructor, 
  97.      * the returned encoding name, being canonical, may differ from the 
  98.      * encoding name passed to the constructor.  May return <code>null</code> 
  99.      * if the stream has been closed.
  100.      */
  101.     public String getEncoding() {
  102.     synchronized (lock) {
  103.         if (btc != null)
  104.         return btc.getCharacterEncoding();
  105.         else
  106.         return null;
  107.     }
  108.     }
  109.  
  110.  
  111.     /* Buffer handling */
  112.  
  113.     private int nBytes = 0;    /* -1 implies EOF has been reached */
  114.     private int nextByte = 0;
  115.  
  116.     private void malfunction() {
  117.     throw new InternalError("Converter malfunction (" +
  118.                 btc.getCharacterEncoding() +
  119.                 ") -- please submit a bug report via " +
  120.                 System.getProperty("java.vendor.url.bug"));
  121.     }
  122.  
  123.     private int convertInto(char cbuf[], int off, int end) throws IOException {
  124.     int nc = 0;
  125.     if (nextByte < nBytes) {
  126.         try {
  127.         nc = btc.convert(bb, nextByte, nBytes,
  128.                  cbuf, off, end);
  129.         nextByte = nBytes;
  130.         if (btc.nextByteIndex() != nextByte)
  131.             malfunction();
  132.         }
  133.         catch (ConversionBufferFullException x) {
  134.         nextByte = btc.nextByteIndex();
  135.         nc = btc.nextCharIndex() - off;
  136.         }
  137.     }
  138.     return nc;
  139.     }
  140.  
  141.     private int flushInto(char cbuf[], int off, int end) throws IOException {
  142.     int nc = 0;
  143.     try {
  144.         nc = btc.flush(cbuf, off, end);
  145.     }
  146.     catch (ConversionBufferFullException x) {
  147.         nc = btc.nextCharIndex() - off;
  148.     }
  149.     return nc;
  150.     }
  151.  
  152.     private int fill(char cbuf[], int off, int end) throws IOException {
  153.     int nc = 0;
  154.  
  155.     if (nextByte < nBytes)
  156.         nc = convertInto(cbuf, off, end);
  157.  
  158.     while (off + nc < end) {
  159.  
  160.         if (nBytes != -1) {
  161.         if ((nc > 0) && !inReady())
  162.             break;    /* Block at most once */
  163.         nBytes = in.read(bb);
  164.         }
  165.  
  166.         if (nBytes == -1) {
  167.                 nBytes = 0; /* Allow file to grow */
  168.         nc += flushInto(cbuf, off + nc, end);
  169.         if (nc == 0)
  170.             return -1;
  171.         else
  172.             break;
  173.         }
  174.         else {
  175.         nextByte = 0;
  176.         nc += convertInto(cbuf, off + nc, end);
  177.         }
  178.     }
  179.     return nc;
  180.     }
  181.  
  182.     /**
  183.      * Tell whether the underlying byte stream is ready to be read.  Return
  184.      * false for those streams that do not support available(), such as the
  185.      * Win32 console stream.
  186.      */
  187.     private boolean inReady() {
  188.     try {
  189.         return in.available() > 0;
  190.     } catch (IOException x) {
  191.         return false;
  192.     }
  193.     }
  194.  
  195.  
  196.     /** Check to make sure that the stream has not been closed */
  197.     private void ensureOpen() throws IOException {
  198.     if (in == null)
  199.         throw new IOException("Stream closed");
  200.     }
  201.  
  202.     /**
  203.      * Read a single character.
  204.      *
  205.      * @return The character read, or -1 if the end of the stream has been
  206.      *         reached
  207.      *
  208.      * @exception  IOException  If an I/O error occurs
  209.      */
  210.     public int read() throws IOException {
  211.     char cb[] = new char[1];
  212.     if (read(cb, 0, 1) == -1)
  213.         return -1;
  214.     else
  215.         return cb[0];
  216.     }
  217.  
  218.     /**
  219.      * Read characters into a portion of an array.
  220.      *
  221.      * @param      cbuf  Destination buffer
  222.      * @param      off   Offset at which to start storing characters
  223.      * @param      len   Maximum number of characters to read
  224.      *
  225.      * @return     The number of characters read, or -1 if the end of the stream
  226.      *             has been reached
  227.      *
  228.      * @exception  IOException  If an I/O error occurs
  229.      */
  230.     public int read(char cbuf[], int off, int len) throws IOException {
  231.     synchronized (lock) {
  232.         ensureOpen();
  233.             if ((off < 0) || (off > cbuf.length) || (len < 0) ||
  234.                 ((off + len) > cbuf.length) || ((off + len) < 0)) {
  235.                 throw new IndexOutOfBoundsException();
  236.             } else if (len == 0) {
  237.                 return 0;
  238.             }
  239.         return fill(cbuf, off, off + len);
  240.     }
  241.     }
  242.  
  243.     /**
  244.      * Tell whether this stream is ready to be read.  An InputStreamReader is
  245.      * ready if its input buffer is not empty, or if bytes are available to be
  246.      * read from the underlying byte stream.
  247.      *
  248.      * @exception  IOException  If an I/O error occurs
  249.      */
  250.     public boolean ready() throws IOException {
  251.     synchronized (lock) {
  252.         ensureOpen();
  253.         return (nextByte < nBytes) || inReady();
  254.     }
  255.     }
  256.  
  257.     /**
  258.      * Close the stream.
  259.      *
  260.      * @exception  IOException  If an I/O error occurs
  261.      */
  262.     public void close() throws IOException {
  263.     synchronized (lock) {
  264.         if (in == null)
  265.         return;
  266.         in.close();
  267.         in = null;
  268.         bb = null;
  269.         btc = null;
  270.     }
  271.     }
  272.  
  273. }
  274.